package com.smart.common.mybatis.wrappers;

import java.util.Map;
import java.util.Set;
import java.util.List;
import java.util.HashMap;
import java.lang.reflect.Field;
import org.apache.commons.lang.StringUtils;
import com.smart.common.mybatis.util.FieldUtil;
import com.baomidou.mybatisplus.annotation.TableField;
import com.smart.common.mybatis.constants.ValuePrefix;
import com.smart.common.mybatis.constants.ParamNameSuffix;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;

/**
 * @author lgb
 * @date 2020年6月13日 上午11:03:02
 * Copyright (C) 深圳工勘科技
 * @说明: @param <T> 高级查询包装器
 **/
public class HightQueryWrapper<T> extends QueryWrapper<T> {

	private static final long serialVersionUID = -2789816849880643280L;

	/**
	 * 构建一个高级查询包装器
	 * @param entity        实体类对象
	 * @param requestParams 请求参数集合
	 * @param <E>
	 * @return
	 **/
	public static <E> HightQueryWrapper<E> wrapper(E entity, Map<String, String[]> requestParams) {
		Map<String, String> tempMap = new HashMap<>(requestParams.size());
		if (requestParams != null && !requestParams.isEmpty()) {
			requestParams.forEach((k, v) -> tempMap.put(k, v[0]));
		}
		return new HightQueryWrapper<>(entity, tempMap);
	}

	private HightQueryWrapper(T entity, Map<String, String> requestParams) {
		super.setEntity(null);
		super.initNeed();
		if (entity != null) {
			List<Field> fieldList = FieldUtil.getFieldList(entity.getClass());
			if (fieldList != null && !fieldList.isEmpty()) {
				Set<String> paramNames = null;
				if (requestParams != null && !requestParams.isEmpty()) {
					paramNames = requestParams.keySet();
				}
				Set<String> finalParamNames = paramNames;
				fieldList.forEach(field -> {
					try {
						field.setAccessible(true);
						String fieldName = field.getName();//实体类字段名
						String columnName = null;
						TableField tableField = field.getAnnotation(TableField.class);
						if (tableField != null && tableField.exist()) {
							columnName = tableField.value();//数据库字段名
						} else {
							columnName = fieldName.replaceAll("([A-Z])", "_$1").toLowerCase();
						}
						if (finalParamNames != null) {
							// IN 解析
							if (finalParamNames.contains(fieldName + ParamNameSuffix.IN)) {
								String paramValue = requestParams.get(fieldName + ParamNameSuffix.IN);
								if (StringUtils.isNotBlank(paramValue)) {
									String sep = getInSeparator(requestParams, fieldName);
									this.in(columnName, StringUtils.split(paramValue, sep));
								}
							}
							// NOT IN 解析
							if (finalParamNames.contains(fieldName + ParamNameSuffix.NOT_IN)) {
								String paramValue = requestParams.get(fieldName + ParamNameSuffix.NOT_IN);
								if (StringUtils.isNotBlank(paramValue)) {
									String sep = getInSeparator(requestParams, fieldName);
									this.notIn(columnName, StringUtils.split(paramValue, sep));
								}
							}
							//范围值解析
							if (finalParamNames.contains(fieldName + ParamNameSuffix.BEGIN)) {//起始值解析
								String paramValue = requestParams.get(fieldName + ParamNameSuffix.BEGIN);
								if (StringUtils.isNotBlank(paramValue)) {
									this.ge(columnName, paramValue);
								}
							}
							if (finalParamNames.contains(fieldName + ParamNameSuffix.END)) {//结束值解析
								String paramValue = requestParams.get(fieldName + ParamNameSuffix.END);
								if (StringUtils.isNotBlank(paramValue)) {
									this.le(columnName, paramValue);
								}
							}

							//特殊前缀解析
							Object paramValue = requestParams.get(fieldName);
							if (paramValue != null) {
								Object value = field.get(entity);
								if (value != null && StringUtils.isNotBlank(value.toString())) {
									if (StringUtils.startsWith(paramValue.toString(), ValuePrefix.EQ)) {
										this.eq(columnName, value);
									} else if (StringUtils.startsWith(paramValue.toString(), ValuePrefix.NE)) {
										this.ne(columnName, value);
									} else if (StringUtils.startsWith(paramValue.toString(), ValuePrefix.GT)) {
										this.gt(columnName, value);
									} else if (StringUtils.startsWith(paramValue.toString(), ValuePrefix.LT)) {
										this.lt(columnName, value);
									} else if (StringUtils.startsWith(paramValue.toString(), ValuePrefix.GE)) {
										this.ge(columnName, value);
									} else if (StringUtils.startsWith(paramValue.toString(), ValuePrefix.LE)) {
										this.le(columnName, value);
									} else {
										this.like(columnName, value);
									}
								}
								if (StringUtils.startsWith(paramValue.toString(), ValuePrefix.IS_NULL)) {
									this.isNull(columnName);
								} else if (StringUtils.startsWith(paramValue.toString(), ValuePrefix.NOT_NULL)) {
									this.isNotNull(columnName);
								} else if (StringUtils.startsWith(paramValue.toString(), ValuePrefix.IS_EMPTY)) {
									this.eq(columnName, "");
								} else if (StringUtils.startsWith(paramValue.toString(), ValuePrefix.NOT_EMPTY)) {
									this.ne(columnName, "");
								}
							}
						}
					} catch (Exception e) {
						e.printStackTrace();
					}
				});
			}
		}

	}

	private String getInSeparator(Map<String,String> requestParams,String fieldName) {
		String sep = requestParams.get(fieldName + ParamNameSuffix.IN_SEPARATOR);
		if (StringUtils.isBlank(sep)) {
			sep = ParamNameSuffix.DEFAULT_IN_SEPARATOR;
		}
		return sep;
	}
	
}